---
title: Multi-Pass Rendering
---

Multi-pass rendering allows an object to be rendered multiple times, each time using different rendering logic. This tutorial uses the implementation of an outline effect to teach the principles and applications of multi-pass rendering.


<Image
src="https://mdn.alipayobjects.com/huamei_dmxymu/afts/img/A*h7mASJQZe5wAAAAATUAAAAgAeuuHAQ/original"
/>

## What is Multi-Pass Rendering?

Multi-pass rendering refers to executing multiple rendering passes on the same object within a single draw call:

```glsl
SubShader "Default" {
Pass "Outline" {
// First pass: Render the outline
}

Pass "Main" {
// Second pass: Render the object itself
}
}
```

**Execution Order**: The engine will execute the passes sequentially, according to their declaration order. ## Outline Effect Implementation

The outline effect is achieved using two passes:
1. **Outline Pass**: Renders the back face of the enlarged object to create the outline.
2. **Main Pass**: Renders the front face of the object normally.

## Complete Shader Example

```glsl
Shader "Tutorial/04-Outline" {
SubShader "Default" {
// Pass 1: Outline Pass - Render the enlarged back face first
Pass "Outline" {
// Rendering state: Only render the front face for outlining
RasterState customRasterState {
CullMode = CullMode.Front;  // Cull front face, only render back face
}

DepthState customDepthState {
WriteEnabled = true;
CompareFunction = CompareFunction.LessEqual;
}

RasterState = customRasterState;
DepthState = customDepthState;


mat4 renderer_MVPMat;
vec4 material_OutlineColor;
float material_OutlineWidth;

struct a2v {
vec4 POSITION;
vec3 NORMAL;
};

VertexShader = outlineVert;
FragmentShader = outlineFrag;

// Outline vertex shader: Expand vertices along the normal direction
void outlineVert(a2v input) {
// Expand the vertex along the normal direction
vec4 pos = input.POSITION;
pos.xyz += input.NORMAL * material_OutlineWidth;

gl_Position = renderer_MVPMat * pos;
}

// Outline fragment shader: Output the outline color
void outlineFrag() {
gl_FragColor = material_OutlineColor;
}
}

// Pass 2: Main Pass - Render the object itself
Pass "Main" {
// Rendering state: Render the back face normally
RasterState customRasterState {
CullMode = CullMode.Back;   // Cull back face, render front face
}

DepthState customDepthState {
WriteEnabled = true;
CompareFunction = CompareFunction.LessEqual;
}

RasterState = customRasterState;
DepthState = customDepthState;

mat4 renderer_MVPMat;
vec4 material_BaseColor;
vec3 camera_Position;

struct a2v
``` {
vec4 POSITION;
vec3 NORMAL;
};

struct v2f {
vec3 worldNormal;
vec3 worldPos;
};

VertexShader = mainVert;
FragmentShader = mainFrag;

// Main vertex shader
v2f mainVert(a2v input) {
v2f output;

gl_Position = renderer_MVPMat * input.POSITION;

// Pass world space normal and position (simplified processing)
output.worldNormal = input.NORMAL;
output.worldPos = input.POSITION.xyz;

return output;
}

// Main fragment shader: Simple Lambert shading
void mainFrag(v2f input) {
vec3 normal = normalize(input.worldNormal);
vec3 lightDir = normalize(vec3(1.0, 1.0, 1.0)); // Fixed light direction

// Lambertian diffuse shading
float NdotL = max(dot(normal, lightDir), 0.0);
vec3 diffuse = material_BaseColor.rgb * NdotL;

// Add ambient light
vec3 ambient = material_BaseColor.rgb * 0.3;

gl_FragColor = vec4(diffuse + ambient, material_BaseColor.a);
}
}
```

## Common Application Scenarios of Multi-Pass Rendering

### 1. Outline Effect
- First pass renders the outline
- Second pass renders the object itself

### 2. Shadow Rendering
- First pass generates the shadow map
- Second pass renders using the shadow map

### 3. Post-processing Effects
- Multiple passes implement complex post-processing pipelines

### 4. Multi-layered Materials
- Each pass renders a different material layer

## Performance Considerations

Multi-pass rendering increases the number of draw calls:
- **Advantages**: Implements complex effects, clear logic
- **Disadvantages**: Larger performance overhead
- **Recommendation**: Pay attention to rendering state issues such as depth writing

## Running Results

This shader will:
* Render a black outline in the first pass (backface, enlarged)
* The second pass renders a standard textured object.
* The two passes are combined to create an outline effect.
* You can adjust the outline width and color.

Go to [Playground](/examples/shaderlab-04-multi-pass)